//主要功能是将接收到的格式化信息进行定向输出
#ifndef SINK_HPP
#define SINK_HPP
#include "util.hpp"
#include <memory>
#include <fstream>
#include <assert.h>
#include <sstream>
namespace blog
{
    class logSink
    {
    public:
        using ptr=std::shared_ptr<logSink>;
        // logSink();
        //virtual ~logSink();
        virtual void log(const char* data,size_t len)=0;
    };

    class stdoutSink:public logSink
    {
    public:
        void log(const char*data,size_t len) override
        {
            std::cout.write(data,len);
        }
    };
    
    class fileSink:public logSink
    {
    public:
        fileSink(const std::string& filename):_filename(filename)
        {
            //先创建文件夹
            util::file::createDirectory(util::file::path(filename));
            //创建并打开文件
            _ofs.open(filename,std::ios::binary|std::ios::app);
            assert(_ofs.is_open());
        }
        void log(const char*data,size_t len) override
        {
            _ofs.write(data,len);
            assert(_ofs.good());
        }
    private:
        std::ofstream _ofs;
        std::string _filename;
    };
    class rollBySizeFileSink:public logSink
    {
    public:
        rollBySizeFileSink(const std::string& filename,size_t msize)
        :_filename(filename),
        _msize(msize),
        _csize(0)
        {
             std::string pathname=createNewFile();
            //先创建文件夹
            util::file::createDirectory(util::file::path(pathname));
            //打开文件
            _ofs.open(pathname,std::ios::binary|std::ios::app);
            assert(_ofs.is_open());
        }
        void log(const char*data,size_t len) override
        {
            //如果len直接大于了msize的情况这个函数还没有解决这个问题
            if(_csize>=_msize)
            {
                _csize=0;
                _ofs.close();
                std::string pathname=createNewFile();
                _ofs.open(pathname,std::ios::binary|std::ios::app);
                assert(_ofs.is_open());
            } 
            _ofs.write(data,len);
            assert(_ofs.good());
            _csize+=len;
        }
    private:
        std::string createNewFile()
        {
            std::stringstream ss;
            time_t t=util::date::now();
            struct tm lt;
            localtime_r(&t,&lt);
            ss<<_filename;
            ss<<lt.tm_year+1900;
            ss<<lt.tm_mon+1;
            ss<<lt.tm_mday;
            ss<<lt.tm_hour;
            ss<<lt.tm_min;
            ss<<lt.tm_sec;
            ss<<"-"<<_test_count++;
            ss<<".log";
            return ss.str();
        }
    private:
        static int _test_count;//测试用的 因为创建的速度小于一秒导致文件覆盖
        std::ofstream _ofs;
        std::string _filename;
        size_t _csize;
        size_t _msize;
    };
    int blog::rollBySizeFileSink::_test_count=0;

    class sinkFactory
    {
    public:
        //C++11的特性还没学这部分先抄下 后面理解
        template<typename SinkType,typename ...Args>
        static logSink::ptr create(Args &&...args)
        {
            return std::make_shared<SinkType>(std::forward<Args>(args)...);
        }

    };





}
#endif